package com.nfha.algorithm.taskassign;

import com.nfha.algorithm.Exerciser;
import java.text.MessageFormat;
import java.util.*;

public class TaskAssignV2Exerciser extends Exerciser{
	
	
	
	// 每组最少人数
		private final static int MIN_GROUP_SIZE = 2;
		
		

		
		
		
		


		// 算法入口
		private static Map<String, Employee[]> calEmployeeGroupBySkill(Collection<Employee> allEmployees,
				String... needSkillIds) {
			Map<String, Employee[]> candidateEmployeeGroupMap = new HashMap<>(), addEmployeeGroupMap = new HashMap<>();
			;

			// 候选组人员
			Set<Employee> candidateEmployees = new HashSet<>();
			for (Employee employee : allEmployees) {
				if (employee.hasSkill(needSkillIds) > 0) {
					// 至少符合一个需求技能才能加入候选组
					candidateEmployeeGroupMap.put(Employee.genGroupId(employee), new Employee[] { employee });
					candidateEmployees.add(employee);
				}

			}

			for (int i = 2; i <= needSkillIds.length; i++) {
				// 两人小组开始计算符合要求的组合
				Map<String, Employee[]> calEmployeeGroupMap = _calEmployeeGroupBySkill(candidateEmployees,
						candidateEmployeeGroupMap, i, needSkillIds);
				addEmployeeGroupMap.putAll(calEmployeeGroupMap);
			}

			// 分级剪纸，类似购物篮的剪枝
			for (int i = 2; i <= needSkillIds.length; i++) {
				Set<String> groupEqiIds = new HashSet<>(), groupGtiIds = new HashSet<>();
				for (String groupId : addEmployeeGroupMap.keySet()) {
					Employee[] addEmployees = addEmployeeGroupMap.get(groupId);
					if (addEmployees.length == i) {
						groupEqiIds.add(groupId);
					} else if (addEmployees.length > i) {
						groupGtiIds.add(groupId);
					}
				}

				for (String groupGtiId : groupGtiIds) {

					for (String groupEqiId : groupEqiIds) {

						if (addEmployeeGroupMap.containsKey(groupGtiId)&&Employee.isContain(addEmployeeGroupMap.get(groupGtiId),
								addEmployeeGroupMap.get(groupEqiId)) >= i) {
							addEmployeeGroupMap.remove(groupGtiId);
						}

					}

				}

			}

			return addEmployeeGroupMap;

		}

		private static Map<String, Employee[]> _calEmployeeGroupBySkill(Set<Employee> candidateEmployees,
				Map<String, Employee[]> candidateEmployeeGroupMap, int groupSize, String... needSkillIds) {
			Map<String, Employee[]> addEmployeeGroupMap = new HashMap<>();
			String[] groupIds = candidateEmployeeGroupMap.keySet().toArray(new String[candidateEmployeeGroupMap.size()]);
			for (String groupId : groupIds) {
				Employee[] employees = candidateEmployeeGroupMap.get(groupId);
				if (employees.length != groupSize - 1)
					continue;

				for (Employee candidateEmployee : candidateEmployees) {
					Employee[] newEmpGroup = Employee.appendTo(employees, candidateEmployee);
					String newGroupId = Employee.genGroupId(newEmpGroup);
					if (Employee.hasSkill(newEmpGroup, needSkillIds) >= needSkillIds.length
							&& newEmpGroup.length >= MIN_GROUP_SIZE) {
						// 满足所有技能加入执行组
						addEmployeeGroupMap.put(newGroupId, newEmpGroup);
					} else {
						// 未满足所有技能加入候选组
						candidateEmployeeGroupMap.put(newGroupId, newEmpGroup);
					}
				}

			}

			return addEmployeeGroupMap;
		}

		public static List<GroupInfo> calGroupInfo(Collection<Employee> allEmployees, String portCode, String... needSkillIds) {
			List<GroupInfo> groupInfos = new ArrayList<>();

			Map<String, Employee[]> employeeGroupMap = calEmployeeGroupBySkill(allEmployees, needSkillIds);

			for (String key : employeeGroupMap.keySet()) {
				GroupInfo groupInfo = new GroupInfo(key, employeeGroupMap.get(key));
				groupInfos.add(groupInfo);
			}
			GroupInfo.updatePriority3(groupInfos);
			GroupInfo.updatePriority4(groupInfos);
			for (int i = 0; i < groupInfos.size(); i++) {
				GroupInfo groupInfo = groupInfos.get(i);
				groupInfo.updatePriority1();
				groupInfo.updatePriority2(portCode);
				
				groupInfo.updateWT(groupInfos);
			}

			
			for (int i = 0; i < groupInfos.size(); i++) {
				GroupInfo groupInfo = groupInfos.get(i);

				groupInfo.updateWTRate(groupInfos);
			}
			return groupInfos;
		}

		
		
		

		
		
		
		
		
//		2.增加X次（可设定，X>200）任务，任务所需要的技能为2到5个技能的随机，码头也随机，每次派单增加的任务都计入个人的待办。
//		每次任务派完后，都显示派单情况和派单后每个人的待办、在办、已办、合计
		
		
		
	

		
		public static <T> Map<String,T> toMap(Collection<T> ts){
			Map<String,T> tm=new HashMap<>();
			for(T t:ts) {
				tm.put(t.toString(), t);
			}
			return tm;
		}
	}
	
	


